package cn.b.sky.shop.activiti.listener;

import cn.b.sky.shop.activiti.constans.GlobalDefine;
import cn.b.sky.shop.activiti.enums.FlowNodeUserEnum;
import cn.b.sky.shop.activiti.model.DeploymentNode;
import cn.b.sky.shop.activiti.model.FlowNodeUser;
import cn.b.sky.shop.activiti.model.WaitTask;
import cn.b.sky.shop.activiti.service.DeploymentNodeService;
import cn.b.sky.shop.activiti.service.WaitTaskService;
import cn.b.sky.shop.activiti.service.impl.EvunProcessEngine;
import cn.b.sky.common.constants.SystemConstant;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.message.enums.MessageCodeEnum;
import cn.b.sky.message.model.MessageUser;
import cn.b.sky.message.service.MessageService;
import cn.b.sky.form.constans.CustomerPageConstans;
import cn.b.sky.form.service.FormObjectService;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.el.ExpressionManager;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.task.IdentityLink;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 
 * <strong>Title : HumanTaskTaskListener.java<br></strong>
 * <strong>Package : cn.b.sky.shop.activiti.listener<br></strong>
 * <strong>Description : </strong>所有用户任务创建时的监听器，设置处理人，发送邮件等操作<br> 
 * <strong>Create on : 2016-12-6 下午3:02:49<br></strong>
 * <p>
 * @author lidapeng<br>
 * @version <strong>v1.0.0</strong><br>
 * <br>
 * <strong>修改历史:</strong><br>
 * 修改人|修改日期|修改描述<br>
 * -------------------------------------------<br>
 * <br>
 * <br>
 */
@Component("humanTaskTaskListener")
public class HumanTaskTaskListener extends DefaultTaskListener {

  /** 
  * @Fields serialVersionUID :
  * @creator     :lidapeng
  */
  private static final long serialVersionUID = 4542083580293254422L;

  private static final Logger LOGGER = LoggerFactory.getLogger(HumanTaskTaskListener.class);

  @Resource
  private DeploymentNodeService deploymentNodeService;

  @Resource
  private EvunProcessEngine evunProcessEngine;

  @Resource
  private MessageService messageService;

  @Resource
  private WaitTaskService waitTaskService;

  @Resource
  private FormObjectService formObjectService;

  @Override
  public void onCreate(DelegateTask delegateTask) {
    //任务创建并设置所有属性后触发
    ProcessDefinitionEntity definition = (ProcessDefinitionEntity) evunProcessEngine
        .getProcessDefinitionById(delegateTask.getProcessDefinitionId());
    String activityId = delegateTask.getExecution().getCurrentActivityId();
    DeploymentNode node = deploymentNodeService.getFlowNodeByDeploymentIdAndActivitId(definition.getDeploymentId(),
        activityId, definition.getTenantId());
    List<FlowNodeUser> users = deploymentNodeService.getFlowNodeUserByDeploymentNodeId(node.getId());
    LOGGER.debug("{}", users);
    if (CollectionUtils.isEmpty(users)) {
      throw ImeException.newException("请配置下一节点处理人!" + delegateTask.getName());
    }
    HistoricProcessInstance his = evunProcessEngine.getHistoricProcessInstanceById(delegateTask.getProcessInstanceId());
    //WaitTask startWaitTask = waitTaskService.getStartWaitTaskByProcessInstance(
    // delegateTask.getTenantId(),delegateTask.getProcessInstanceId());
    //UserInfo user = userService.selectUser(delegateTask.getTenantId(), startor);
    String startor = null;
    String businessKey = null;
    if (his != null) {
      startor = his.getStartUserId();
      businessKey = his.getBusinessKey();
    }
    if (startor == null) {//发起流程时不存在HistoricProcessInstance
      @SuppressWarnings("unchecked")
      Map<String, Object> operationMap = (Map<String, Object>) delegateTask
          .getVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      startor = Authentication.getAuthenticatedUserId();
      businessKey = operationMap.get(GlobalDefine.WorkFlow.BUSINESSKEY).toString();
    }
    //待办任务
    WaitTask waitTask = new WaitTask();
    StringBuilder candidateUsers = new StringBuilder("");
    StringBuilder candidateGroups = new StringBuilder("");
    for (FlowNodeUser user : users) {
      String values = user.getValue();
      if (values.startsWith("${")) {
        ExpressionManager expressionManager = Context.getProcessEngineConfiguration().getExpressionManager();
        values = expressionManager.createExpression(values).getValue(delegateTask).toString();
        if (StringUtils.isBlank(values)) {
          throw ImeException.newException("找不到下一节点的接收人" + values);
        }
      }
      //流程发起者,赋值
      if (BpmnParse.PROPERTYNAME_INITIATOR_VARIABLE_NAME.equals(values)) {
        values = startor;
      }
      //前后都加上分隔符为了好匹配字符格式 ,str, 防止重复
      if (user.getType().equals(FlowNodeUserEnum.ASSIGNEE.getCode())) {
        candidateUsers.append(SystemConstant.LABLE_SPLIT).append(values).append(SystemConstant.LABLE_SPLIT);
        delegateTask.setAssignee(values);
      }
      if (user.getType().equals(FlowNodeUserEnum.CANDIDATEUSERS.getCode())) {
        //特殊处理只有一个用户的时候直接就是处理人，不需要接收操作
        candidateUsers.append(SystemConstant.LABLE_SPLIT).append(values).append(SystemConstant.LABLE_SPLIT);
        delegateTask.addCandidateUsers(Arrays.asList(values.split(SystemConstant.LABLE_SPLIT)));
      }

      if (user.getType().equals(FlowNodeUserEnum.CANDIDATEGROUPS.getCode())) {
        candidateGroups.append(SystemConstant.LABLE_SPLIT).append(values).append(SystemConstant.LABLE_SPLIT);
        delegateTask.addCandidateGroups(Arrays.asList(values.split(SystemConstant.LABLE_SPLIT)));
      }
    }
    //发送邮件
    /*String message = "你有一个新的任务需要处理<br/>流程名称：【" + definition.getName() + "】<br/>任务名称：【" + delegateTask.getName()
        + "】<br/>发起人：【" + startor + "】<br/>业务编号：【" + businessKey + "】";*/
    Map<String, String> map = new HashMap<String, String>();
    map.put("definitionName", definition.getName());
    map.put("taskName", delegateTask.getName());
    map.put("startor", startor);
    map.put("businessKey", businessKey);
    //发送消息
    sendMessage(delegateTask, map);

    waitTask.setTaskId(delegateTask.getId());
    waitTask.setCandidateUsers(candidateUsers.toString());
    waitTask.setCreateTime(delegateTask.getCreateTime());
    waitTask.setGroups(candidateGroups.toString());
    waitTask.setTaskName(delegateTask.getName());
    waitTask.setStatus(0);//0待办
    waitTask.setStartor(startor);
    waitTask.setBusinessKey(businessKey);
    waitTask.setProcessDefineName(definition.getName());
    waitTask.setProcessInstanceId(delegateTask.getProcessInstanceId());
    waitTask.setTenantId(delegateTask.getTenantId());
    waitTask.setVersion(definition.getVersion() + "");
    waitTask.setAssignee(getAssigneesByWaitTask(waitTask));
    waitTaskService.saveWaitTask(waitTask);
  }

  /**
   * 
   * <strong>Title : getAssigneesByWaitTask<br></strong>
   * <strong>Description : </strong>最后设置待办任务的处理人，主要是判断如果只有一个人的话,就设置<br> 
   * <strong>Create on : 2016-12-21 下午2:07:08<br></strong>
   * <p>
   * @param waitTask
   * @return
   * String
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  private String getAssigneesByWaitTask(WaitTask waitTask) {
    if (!StringUtils.isBlank(waitTask.getGroups())) {
      return null;
    }
    if (StringUtils.isBlank(waitTask.getCandidateUsers())) {
      return null;
    }
    int i = 0;
    String assignees = null;
    for (String user : waitTask.getCandidateUsers().split(SystemConstant.LABLE_SPLIT)) {
      if (!StringUtils.isBlank(user)) {
        i++;
        assignees = user;
      }
    }
    //如果只有一个值则表明就是唯一处理者
    if (i == 1) {
      return assignees;
    }
    return null;
  }

  private void sendMessage(DelegateTask delegateTask, Map<String, String> map) {
    //分给用户时发送消息
    String assignee = delegateTask.getAssignee();
    MessageUser messageUser = new MessageUser();
    if (!StringUtils.isBlank(assignee)) {
      messageUser.setUserList(assignee.split(SystemConstant.LABLE_SPLIT));
      messageService.sendMessageToGivenUser(delegateTask.getTenantId(), MessageCodeEnum.WORKFLOW_MESSAGE.getValue(),
          messageUser, map);
      return;
    }
    Set<IdentityLink> identitys = delegateTask.getCandidates();
    String candidateUsers = "";
    String groups = "";
    String roles = "";
    if (identitys != null && identitys.size() > 0) {
      for (IdentityLink identityLink : identitys) {
        if (!StringUtils.isBlank(identityLink.getUserId())) {
          candidateUsers += identityLink.getUserId() + ",";
        }
        if (!StringUtils.isBlank(identityLink.getGroupId())) {
          if (identityLink.getGroupId().indexOf(SystemConstant.USER_ORG) != -1) {
            groups += identityLink.getGroupId().replaceAll(SystemConstant.USER_ORG, "") + ",";
          } else if (identityLink.getGroupId().indexOf(SystemConstant.USER_ROLE) != -1) {
            roles += identityLink.getGroupId().replaceAll(SystemConstant.USER_ROLE, "") + ",";
          }
        }
      }
      messageUser.setUserList(candidateUsers.split(SystemConstant.LABLE_SPLIT));
      messageUser.setOrgList(groups.split(SystemConstant.LABLE_SPLIT));
      messageUser.setRoleList(roles.split(SystemConstant.LABLE_SPLIT));
      messageService.sendMessageToGivenUser(delegateTask.getTenantId(), MessageCodeEnum.WORKFLOW_MESSAGE.getValue(),
          messageUser, map);
    }
  }

  @Override
  public void onComplete(DelegateTask delegateTask) {
    //设置流程变量系统内置的通过不通过
    if (delegateTask.getVariable("ispass") != null) {
      String ispass = (String) delegateTask.getVariable("ispass");
      if (!StringUtils.isBlank(ispass)) {
        delegateTask.setVariable("ispass", "0".equals(ispass) ? true : false);
      }
    }
    String formKey = delegateTask.getFormKey();
    //保存业务对象，针对自定义表单，单表操作，非自定义则直接是url包含/
    if (!StringUtils.isBlank(formKey) && formKey.indexOf("/") == -1) {
      Map<String, Object> operationMap = (Map<String, Object>) delegateTask
          .getVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      operationMap.put(GlobalDefine.WorkFlow.CUREENTSITECODE, delegateTask.getTenantId());
      operationMap.put(CustomerPageConstans.PROCESSINSTANCEID, delegateTask.getProcessInstanceId());
      //防止疏漏
      if (!operationMap.containsKey(CustomerPageConstans.BUSINESSCODE)
          || operationMap.get(CustomerPageConstans.BUSINESSCODE) == null) {
        operationMap.put(CustomerPageConstans.BUSINESSCODE, operationMap.get(GlobalDefine.WorkFlow.BUSINESSKEY));
      }
      try {
        formObjectService.modifyFormObjectData(operationMap, formKey, delegateTask.getTenantId());
        //表单数据存入流程变量 add by zhaox 2017 03 10
        for (Map.Entry<String, Object> entry : operationMap.entrySet()) {
          delegateTask.setVariable(entry.getKey(), entry.getValue());
        }
      } catch (Exception e) {
        LOGGER.error("保存表单对象失败" + formKey, e);
        throw ImeException.newException("保存表单对象失败" + formKey, e);
      }
    }
    //当任务完成，并尚未从运行数据中删除时触发
    //移除业务数据
    delegateTask.removeVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
  }

}
